#!/bin/bash


#-----------------------------------------------------------------------#
#SETUP

set -o errexit -o nounset -o pipefail
IN=""
NULL=""
CC_FLAGS="-Wall -pipe -std=c99 -ggdb -O0 -fno-omit-frame-pointer"
relic_s="relic-0.3.5"
relic_t="relic-target"
DIR_BIN="bin/"
DIR_SRC="src/"
word=$NULL
PRECI=1024
SQFT_VERSION=0
dir_word=$NULL
LOOP="ON"


#-----------------------------------------------------------------------#

header(){
echo "
	 University of Brasilia
	 _______________________
	|u          N          u|
	|  U.       N       .U  |
	|    nN,    N    ,Nn    |
	|       .7BBNBB3.       |
	|           N           |
	|___________N___________|

	  Computer Science Dep."
echo
echo "-----------"
echo "- Manager - Type 'help' for usage"
echo "-----------"
}

#-----------------------------------------------------------------------#

unb(){
echo "
	OOOOOOOOOOOO OOOOOOOOOOOO
	73 OOOOOOOOO OOOOOOOOO 73
	73737 OOOOOO OOOOOO 73737
	73737373=... ...=73737373
	737373737373 737373737373
	737373737373 737373737373

	UNIVERSIDADE DE BRASILIA"
}

#-----------------------------------------------------------------------#

read_history() {
    local char=
    local string=
    local -a history=( )
    local -i histindex=0

    while IFS= read -r -n 1 -s char
    do
        if [ "$char" == $'\x1b' ]
        then
            while IFS= read -r -n 2 -s rest
            do
                char+="$rest"
                break
            done
        fi

        if [ "$char" == $'\x1b[A' ]
        then
            # Up
            if [ $histindex -gt 0 ]
            then
                histindex+=-1
                echo -ne "\r\033[K${history[$histindex]}"
            fi
        elif [ "$char" == $'\x1b[B' ]
        then
            # Down
            if [ $histindex -lt $((${#history[@]} - 1)) ]
            then
                histindex+=1
                echo -ne "\r\033[K${history[$histindex]}"
            fi
        elif [ -z "$char" ]
        then
            # Newline
            echo
            history+=( "$string" )
            string=
            histindex=${#history[@]}
        else
            echo -n "$char"
            string+="$char"
        fi
    done
}

#-----------------------------------------------------------------------#

reset(){
	IN=""
	CC_FLAGS="-Wall -pipe -std=c99 -ggdb -O0 -fno-omit-frame-pointer"
	PRECI=1024
	SQFT_VERSION=0
}

#-----------------------------------------------------------------------#

update(){
	CC_FLAGS="$CC_FLAGS -D SQFT_VERSION=$SQFT_VERSION"
}


#-----------------------------------------------------------------------#

clean(){
	rm rabin.out
	rm sqft.out
}


#-----------------------------------------------------------------------#
tc_chart(){
	gnuplot <<- EOF
		set xlabel "Bits"
		set ylabel "% do tempo gasto"
		set term png
		set output "charts/tc.png"
		plot  "sts/mr2.dat" using 1:2 with lines title 'MR2', \
			"sts/jac.dat" using 1:2 with lines title 'Jacobian', \
			"sts/cmp1.dat" using 1:2 with lines title 'Cmp 1', \
			"sts/cmp2.dat" using 1:2 with lines title 'Cmp 2'
	EOF
	eog charts/tc.png
}


#-----------------------------------------------------------------------#
gen_tc_chart(){
	echo "Generating chart..."
	if [ "$1" == "" ]
	then 
		./"$DIR_BIN"tc junk
	else
		./"$DIR_BIN"tc
	fi
	gnuplot <<- EOF
		set xlabel "Bits"
		set ylabel "$1tempo gasto"
		set term png
		set output "charts/tc.png"
		plot  "sts/mr2.dat" using 1:2 with lines title 'MR2', \
			"sts/jac.dat" using 1:2 with lines title 'Jacobian', \
			"sts/cmp1.dat" using 1:2 with lines title 'Cmp 1', \
			"sts/cmp2.dat" using 1:2 with lines title 'Cmp 2'
	EOF
	echo "Showing chart"
	eog charts/tc.png
}

#-----------------------------------------------------------------------#
gen_chart(){
	echo
	echo "Enter the size (in bits) for prime test or (empty) to test all sizes."
	read size
	echo "Generating chart..."
	if [ "$size" = "" ]
	then
		./"$DIR_BIN"opt
		gnuplot <<- EOF
			set xlabel "Log base 2 dos bits"
			set ylabel "Tempo em micro segundos"
			set term png
			set output "charts/cmp.png"
			plot  "sts/rabin.dat" using 1:2 with lines title 'Rabin', \
				"sts/sqft.dat" using 1:2 with lines title 'SQFT'
		EOF
		echo
		echo "# 2^bits	Time"
	else
		./"$DIR_BIN"opt $size
			gnuplot <<- EOF
			set xlabel ""
			set ylabel "Tempo em micro segundos"
			set term png
			set output "charts/cmp.png"
			plot  "sts/rabin.dat" with lines title 'Rabin', \
				"sts/sqft.dat" with lines title 'SQFT'

		EOF
		echo
		echo "# Times for $size"
		echo "# n - Time"
	fi
	echo
	pr -m -t sts/rabin.dat sts/sqft.dat
	echo
	echo "Showing chart"
	eog charts/cmp.png
}


#-----------------------------------------------------------------------#

gen_all_sqft(){
	compile_sqfts
	echo
	echo "Enter the size (in bits) for prime test or (empty) to test all sizes."
	read size
	echo "Generating chart..."
	if [ "$size" = "" ]
	then
		./"$DIR_BIN"sqfts
		gnuplot <<- EOF
			set xlabel "Log base 2 dos bits"
			set ylabel "Tempo em micro segundos"
			set term png
			set output "charts/sqfts.png"
			plot  "sts/sqft1.dat" using 1:2 with lines title 'SQFT v1', \
				"sts/sqft2.dat" using 1:2 with lines title 'SQFT v2', \
				"sts/sqft3.dat" using 1:2 with lines title 'SQFT v3', \
				"sts/sqft4.dat" using 1:2 with lines title 'SQFT v4', \
				"sts/sqft5.dat" using 1:2 with lines title 'SQFT v5'
		EOF
		echo
		echo "# 2^bits	Time"
	else
		./"$DIR_BIN"opt $size
			gnuplot <<- EOF
			set xlabel ""
			set ylabel "Tempo em micro segundos"
			set term png
			set output "charts/sqfts.png"
			plot  "sts/sqft1.dat" using 1:2 with lines title 'SQFT v1', \
				"sts/sqft2.dat" using 1:2 with lines title 'SQFT v2', \
				"sts/sqft3.dat" using 1:2 with lines title 'SQFT v3', \
				"sts/sqft4.dat" using 1:2 with lines title 'SQFT v4', \
				"sts/sqft5.dat" using 1:2 with lines title 'SQFT v5'

		EOF
		echo
		echo "# Times for $size"
		echo "# n - Time"
	fi
	echo
	pr -m -t sts/sqft1.dat sts/sqft2.dat sts/sqft3.dat sts/sqft4.dat sts/sqft5.dat
	echo
	echo "Showing chart"
	eog charts/sqfts.png
}


#-----------------------------------------------------------------------#

gen_lier_chart(){
	compile_lier
	echo
	echo "Enter the size (in bits) for prime test or (empty) to test all sizes."
	read size
	echo "Generating chart..."
	if [ "$size" = "" ]
	then
		./"$DIR_BIN"lier
		gnuplot <<- EOF
			set xlabel "Log base 2 dos bits"
			set ylabel "Tempo em micro segundos"
			set term png
			set output "charts/lier.png"
			plot  "sts/lier_rabin.dat" using 1:2 with lines title 'Rabin', \
				"sts/lier_sqft.dat" using 1:2 with lines title 'SQFT'
		EOF
		echo
		echo "# 2^bits	Time"
	else
		./"$DIR_BIN"lier $size
			gnuplot <<- EOF
			set xlabel ""
			set ylabel "Tempo em micro segundos"
			set term png
			set output "charts/lier.png"
			plot  "sts/lier_rabin.dat" with lines title 'Rabin', \
				"sts/lier_sqft.dat" with lines title 'SQFT'

		EOF
		echo "# Times for $size"
		echo "# n - Time"
	fi
	echo
	pr -m -t sts/lier_rabin.dat sts/lier_sqft.dat
	echo
	echo "Showing chart..."
	eog charts/lier.png
}


#-----------------------------------------------------------------------#

help(){
	echo
	echo "RELIC:"
	echo "	relic-compile ARGS...	: run cmake and full compile relic."
	echo "				ARGS:"
	echo "				word	: Set word size for compilation."
	echo "					  if none, default 'word=[OS arch]'"
	echo "				preci	: Set relic precision in bits."
	echo "					  if none, default 'preci=1024'"
	echo "	relic-make		: just run make and compile relic."
	echo
	echo "TESTS:"
	echo "	test			: compile and run test."
	echo "	bench			: compile and run bench."
	echo "	chart			: compile, run and show Rabin vs SQFT chart."
	echo "	tc%			: compile, run and show Time Consuming percent for SQFT."
	echo "	tc			: compile, run and show Time Consuming values for SQFT."
	echo "	lier			: compile, run and show SQFT vs Rabin for compositeness."
	echo "	sqft			: compile, run and show all SQFT versions compare chart."
	echo "	bench-cmp		: compile and run own bench for functions."
	echo
	echo "Note: You can choose the version of SQFT by adding 'vx' after the command, where 'x' is the version. Man will use latest version if empty."
	echo " Exemple: 'chart v2'"
	echo
	echo "EXIT:"
	echo "	exit	: exit manager."
	echo
	exit
}

#-----------------------------------------------------------------------#
gen_chart_i(){
	echo
	echo "Enter the size (in bits) for prime test or (empty) to test all sizes."
	read size
	echo "Generating chart..."
	echo
	if [ "$size" = "" ]
	then
		./"$DIR_BIN"opt_i sqft.out
		./"$DIR_BIN"opt_i rabin.out
		java -jar kchart-gen.jar /rabin.out /sqft.out bits
	else
		./"$DIR_BIN"opt_i sqft.out $size
		./"$DIR_BIN"opt_i rabin.out $size
		java -jar kchart-gen.jar /rabin.out /sqft.out "$size bits"
	fi

	clean
}

#-----------------------------------------------------------------------#

relic_compile(){
	echo Compiling Relic
	FLAGS="-O2 -funroll-loops" CC=gcc cmake -DWORD="$word" -DARITH=gmp -DDEBUG=ON -DBN_PRECI="$PRECI" -DVERBS=ON ../../"$relic_s"
	relic_make
	return
}

#-----------------------------------------------------------------------#

relic_make(){
	make
	return
}

#-----------------------------------------------------------------------#

check_dir(){
	if [ ! -d $dir_word ]
	then
		mkdir $dir_word
		cd $dir_word
		mkdir $relic_t
		cd $relic_t
		cd ../..
	fi
	
	if [ ! -d $DIR_BIN ]
	then
		mkdir $DIR_BIN
	fi
	
	if [ ! -d $DIR_SRC ]
	then
		mkdir $DIR_SRC
	fi
}

#-----------------------------------------------------------------------#

compile_test(){
	gcc $CC_FLAGS "$DIR_SRC"test.c -o "$DIR_BIN"test -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp
}

#-----------------------------------------------------------------------#

compile_bench(){
	gcc $CC_FLAGS "$DIR_SRC"bench.c -o "$DIR_BIN"bench -w -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lrt -lgmp
}

#-----------------------------------------------------------------------#

compile_opt(){
	gcc $CC_FLAGS "$DIR_SRC"opt.c -o "$DIR_BIN"opt -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp -lm
}

#-----------------------------------------------------------------------#

compile_opt_i(){
	gcc $CC_FLAGS "$DIR_SRC"opt_i.c -o "$DIR_BIN"opt_i -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp -lm
}

#-----------------------------------------------------------------------#

compile_tc(){
	gcc $CC_FLAGS "$DIR_SRC"time_consuming.c -o "$DIR_BIN"tc -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp -lm
}

#-----------------------------------------------------------------------#

compile_lier(){
	gcc $CC_FLAGS "$DIR_SRC"lier.c -o "$DIR_BIN"lier -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp -lm
}

#-----------------------------------------------------------------------#

compile_sqfts(){
	gcc $CC_FLAGS "$DIR_SRC"sqft_versions.c -o "$DIR_BIN"sqfts -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp -lm
}

#-----------------------------------------------------------------------#

compile_bench_cmp(){
	gcc $CC_FLAGS "$DIR_SRC"bench_cmp.c -o "$DIR_BIN"bench_cmp -I"$dir_word"/"$relic_t"/include -I"$relic_s"/include -I"$relic_s"/low -L"$dir_word"/"$relic_t"/lib -lrelic_s -lgmp -lm
}

#-----------------------------------------------------------------------#


compile_all_tests(){
	compile_test
	compile_bench
	compile_opt
	compile_tc
}

#-----------------------------------------------------------------------#

# MAIN

clear
header

while [ $LOOP = "ON" ]; do
reset
echo
#read history
while [ "$IN" = "$NULL" ];
do
	IFS="" read -r -e -d $'\n' -p '> ' line
	history -s "$line"
	IN=$line
done

IFS=' ' a_split=($IN)
word=64

for i in ${a_split[@]}
do
	case "$i" in
		"exit") LOOP=OFF
			exit;;
		"help") help;;
		"64") word=64;;
		"32") word=32;;
	esac
	j=$i
	# check for word size
	IFS='=' e_split=($j)
	if [ "${e_split[0]}" == "word" ]
	then
		word=${e_split[1]}
	fi
	
	# check for precision
	if [ "${e_split[0]}" == "preci" ]
	then
		PRECI=${e_split[1]}
	fi
	
done
IFS=' '

if [ "$word" = "$NULL" ]
then
	arc=$(uname -i)
	if [ "$arc" = "x86_64" ]
	then 
		word="64"
	elif [ "arc" = "i386" ]
	then
		word="32"
	else
		word="32"
	fi
fi

dir_word=$word

echo "word set as $word"

check_dir

for i in ${a_split[@]}
do
	case "$i" in
		
		"relic-compile") cd $dir_word/$relic_t
			relic_compile
			cd ../.. ;;
		"relic-make") cd $dir_word/$relic_t
			relic_make
			cd ../.. ;;
		"v1") SQFT_VERSION=1;;
		"v2") SQFT_VERSION=2;;
		"v3") SQFT_VERSION=3;;
		"v4") SQFT_VERSION=4;;
		"v5") SQFT_VERSION=5;;
	esac
done

update

#-----------------------------------------------------------------------#

#echo ------------------------------------
#echo "Compiling test"
#echo ------------------------------------

#-----------------------------------------------------------------------#

for i in ${a_split[@]}
do
	case "$i" in
		"chart") compile_opt
			gen_chart;;
		"charti") compile opt_i
			gen_chart_i;;
		"tc") compile_tc
			gen_tc_chart "";;
		"tc%") compile_tc
			gen_tc_chart "% do ";;
		"test") compile_test
			./"$DIR_BIN"test;;
		"bench") compile_bench
			./"$DIR_BIN"bench;;
		"lier") gen_lier_chart;;
		"sqft") gen_all_sqft;;
		"bench-cmp") compile_bench_cmp
			./"$DIR_BIN"bench_cmp;;
		"compile-all") compile_all_tests;;
	esac
done

done


